/*
 * @Description: xxx描述文件内容
 * @Autor: gufuyan
 * @Date: 2021-11-16 17:16:14
 * @lastModifiedBy: gufuyan
 * @LastEditTime: 2021-12-03 16:52:50
 * @lastModifiedContent: xxx描述修改的内容
 */

import React, { useState, useEffect } from 'react';
import { Input, Select, DatePicker, Tag, TreeSelect, message } from 'antd';
import type { ProColumns } from '@ant-design/pro-table';
import { EditableProTable } from '@ant-design/pro-table';
import { useModel } from 'umi';
import moment from 'moment';
import { intl } from '../FormAttributes';
import InputTagList from './InputTagList';
import { validationRules, dateFormula, dateDesc, dateType } from './constants';
import type {
  FieldNameTree,
  RuleOptions,
  DataSourceType,
  IEditableFieldProps,
  EditRow,
  Option,
} from './data';

const { RangePicker } = DatePicker;

/**
 *编辑规则表格
 * @param props
 * @returns
 */
const EditableField: React.FC<IEditableFieldProps> = (props) => {
  const drag = useModel('drag');
  // 表格数据，是否在编辑状态
  const { dataSource, setDataSource, setIsEdit } = { ...props };
  // 正在编辑行 key
  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  // 表格字段-字段名称，下拉选项，根据拖拽页面的组件计算得出
  const [fieldNameTree, setFieldNameTree] = useState<FieldNameTree[]>([]);
  const [fieldNameObj, setFieldNameObj] = useState<Record<string, FieldNameTree>>({});
  // 表格字段-匹配规则，下拉选项，根据字段名称的类型计算得出
  const [ruleOptions, setRuleOptions] = useState<Record<string, RuleOptions>>();
  // 正在编辑的行数据
  const [editRow, setEditRow] = useState<EditRow>({});

  // 日期取值
  const [formulaType, setFormulaType] = useState<string>();
  const [date, setDate] = useState<Date | string>();
  const [dateRange, setDateRange] = useState<string[]>();
  const [formulaFlag, setFormulaFlag] = useState<string>('custom');
  const [formulaNum, setFormulaNum] = useState<string>('1');
  const [formulaTime, setFormulaTime] = useState<string>('day');

  // 日期组件-动态筛选-自定义-的数量选择
  const dateNum = (num: number = 100) => {
    const options = [];
    for (let i = 1; i <= num; i++) {
      options.push({
        label: i,
        value: i,
      });
    }
    return options;
  };

  // 表格配置
  const columns: ProColumns<DataSourceType>[] = [
    {
      title: intl('drag.exp.imp.fieldName'), // 字段名称
      dataIndex: 'fieldName',
      width: 160,
      renderFormItem: (_, record: any) => {
        return (
          <TreeSelect
            showSearch
            style={{ width: '100%' }}
            value={editRow.fieldId}
            dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
            placeholder="请选择"
            allowClear
            treeDefaultExpandAll
            treeData={fieldNameTree}
            onChange={(value) => {
              const rowData = fieldNameObj && fieldNameObj[value];
              if (!rowData) {
                //清除按钮key为空的捕获
                setEditRow({});
                return;
              }

              // 设置编辑的行信息，显隐、逻辑校验使用
              setEditRow({
                id: record.rowKey,
                rule: '',
                fieldId: rowData.value,
                fieldText: rowData.title,
                fieldType: rowData.type,
                fieldName: rowData.fieldName,
                fieldOptions: rowData.fieldOptions,
              });

              // 根据选择的组件类型，设置对应的匹配规则
              const newRuleOptions = {};
              for (const o in validationRules) {
                if (validationRules[o].types.includes(rowData.type)) {
                  newRuleOptions[o] = validationRules[o];
                }
              }
              setRuleOptions(newRuleOptions);
            }}
          />
        );
      },
      render: (_, record: any) => {
        return record.fieldNameText;
      },
    },
    {
      title: intl('drag.exp.imp.rule'), // 匹配规则
      dataIndex: 'rule',
      valueType: 'select',
      valueEnum: ruleOptions,
      width: 140,
      fieldProps: () => {
        return {
          disabled: editRow.fieldText ? false : true,
          value: editRow.rule,
          onChange: (key: string) => {
            setEditRow({ ...editRow, rule: key });
          },
        };
      },
    },
    {
      title: intl('drag.exp.imp.checkValue'), // 校验值
      dataIndex: 'checkValue',
      renderFormItem: () => {
        // 匹配规则没有，则不显示校验值的配置；为空、不为空，无需校验值的配置
        if (!editRow?.rule || ['empty', 'not_empty'].includes(editRow?.rule)) {
          return null;
        }

        switch (editRow?.fieldType) {
          case 'input':
            if (['in', 'nin'].includes(editRow?.rule)) {
              // 等于任意一个、不等于任意一个，切换成标签输入功能
              return <InputTagList />;
            } else {
              return (
                <Input
                  placeholder="请输入"
                  value={editRow.checkValue}
                  onChange={(e) => setEditRow({ ...editRow, checkValue: e.currentTarget.value })}
                />
              );
            }
          case 'radio':
          case 'select':
            if (['eq', 'ne'].includes(editRow?.rule)) {
              // 等于、不等于，切换单选下拉
              return (
                <>
                  <Select
                    placeholder="请选择"
                    value={editRow?.checkValue?.value}
                    options={editRow?.fieldOptions || []}
                    onChange={(_, option) => {
                      setEditRow({ ...editRow, checkValue: option });
                    }}
                  />
                </>
              );
            } else if (['in', 'nin'].includes(editRow?.rule)) {
              // 等于任意一个、不等于任意一个，切换复选下拉
              return (
                <>
                  <Select
                    placeholder="请选择"
                    mode={'multiple'}
                    value={editRow.checkValue?.map((item: { value: string }) => item.value)}
                    options={editRow?.fieldOptions || []}
                    onChange={(_, option) => setEditRow({ ...editRow, checkValue: option })}
                  />
                </>
              );
            } else if (['like', 'unlike'].includes(editRow?.rule)) {
              // 包含、不包含，切换输入框
              return <Input placeholder="请输入" />;
            } else {
              return '';
            }
          case 'checkbox':
            return (
              <Select
                mode="multiple"
                allowClear
                style={{ width: '100%' }}
                options={editRow?.fieldOptions || []}
              />
            );

          case 'datePicker':
          case 'dateRange':
            // 等于、不等于、大于等于、小于等于
            if (['eq', 'ne', 'gte', 'lte'].includes(editRow?.rule)) {
              return (
                <>
                  <DatePicker
                    style={{ width: '100%' }}
                    value={date ? moment(date, 'YYYY-MM-DD') : null}
                    onChange={(_, dateString) => {
                      setDate(dateString);
                    }}
                  />
                </>
              );
            }
            // 选择范围
            if (['range'].includes(editRow?.rule)) {
              return (
                <>
                  <RangePicker
                    style={{ width: '100%' }}
                    value={
                      dateRange
                        ? [moment(dateRange[0], 'YYYY-MM-DD'), moment(dateRange[1], 'YYYY-MM-DD')]
                        : null
                    }
                    onChange={(_, dateString) => {
                      setDateRange(dateString);
                    }}
                  />
                </>
              );
            }
            // 动态筛选
            if (['formula'].includes(editRow?.rule)) {
              return (
                <>
                  <Select
                    style={{ width: 90 }}
                    options={dateFormula}
                    value={formulaType}
                    onChange={(value: string) => {
                      setFormulaType(value);
                    }}
                  />
                  {/* 自定义 */}
                  {formulaType === 'custom' && (
                    <>
                      <Select
                        style={{ width: 80 }}
                        bordered={false}
                        value={formulaFlag}
                        options={dateDesc}
                        onChange={(value) => {
                          setFormulaFlag(value);
                        }}
                      />
                      <Select
                        style={{ width: 60 }}
                        bordered={false}
                        value={formulaNum}
                        options={dateNum()}
                        onChange={(value) => {
                          setFormulaNum(value);
                        }}
                      />
                      <Select
                        style={{ width: 60 }}
                        bordered={false}
                        value={formulaTime}
                        options={dateType}
                        onChange={(value) => {
                          setFormulaTime(value);
                        }}
                      />
                    </>
                  )}
                </>
              );
            }
          default:
            return '';
        }
      },
      render: (_: any, record) => {
        const type = record.fieldName?.split('-')[0];
        switch (type) {
          case 'input':
            // 等于任意一个、不等于任意一个，切换成标签显示；否则显示值
            return ['in', 'nin'].includes(record.rule || '')
              ? record.checkValue?.map((item: Option) => <Tag key={item.value}>{item.label}</Tag>)
              : _;
          case 'radio':
          case 'select':
            // 等于任意一个、不等于任意一个，切换成标签显示；否则显示值(没有label显示自己本身)
            return ['in', 'nin'].includes(record.rule || '')
              ? record.checkValue?.map((item: Option) => <Tag key={item.value}>{item.label}</Tag>)
              : _.label || _;
          case 'checkbox':
            return _;
          case 'datePicker':
          case 'dateRange':
            // 匹配规则为动态筛选时，
            if (['formula'].includes(record.rule || '')) {
              const formula = dateFormula.filter((item) => item.value === _.formulaType)[0];
              const flag = dateDesc.filter((item) => item.value === _.formulaFlag)[0];
              const timeType = dateType.filter((item) => item.value === _.formulaTime)[0];
              // 自定义
              if (_.formulaType === 'custom') {
                return `${formula.label}：${flag.label}${_.formulaNum}${timeType.label}`;
              } else {
                return `${formula.label}`;
              }
            } else {
              return _;
            }
          default:
            return '';
        }
      },
    },
    {
      title: intl('drag.operate'),
      valueType: 'option',
      width: 170,
      render: (text, record: any, _, action) => [
        <a
          key="editable"
          onClick={() => {
            action?.startEditable?.(record.id);
            const currentField: any = fieldNameObj[record.fieldName];
            setEditRow({
              id: record.id,
              rule: record.rule,
              checkValue: record.checkValue,
              fieldType: currentField.type,
              fieldId: record.fieldName,
              fieldText: currentField.title,
              fieldOptions: currentField.fieldOptions,
            });

            const rowData = fieldNameObj[record.fieldName];
            const newRuleOptions: any = {};
            for (const o in validationRules) {
              if (validationRules[o].types.includes(rowData.type)) {
                newRuleOptions[o] = validationRules[o];
              }
            }
            setRuleOptions(newRuleOptions);

            const type = record.fieldName?.split('-')[0];
            if ((type === 'datePicker' || type === 'dateRange') && record.rule === 'formula') {
              setFormulaType(record.checkValue?.formulaType);
              setFormulaFlag(record.checkValue?.formulaFlag);
              setFormulaNum(record.checkValue?.formulaNum);
              setFormulaTime(record.checkValue?.formulaTime);
            }

            setIsEdit(true);
          }}
        >
          {intl('drag.edit')}
        </a>,
        <a
          key="delete"
          onClick={() => {
            setDataSource(dataSource.filter((item) => item.id !== record.id));
          }}
        >
          {intl('drag.delete')}
        </a>,
      ],
    },
  ];

  useEffect(() => {
    const tree: FieldNameTree[] = [];
    const obj: Record<string, FieldNameTree> = {};
    drag.config?.contentItem?.forEach(
      (el: {
        name: string;
        id: string | number;
        title: string;
        field: string;
        props: { options: any };
        children: string | any[];
      }) => {
        if (!['placeBlock', 'splitLine'].includes(el.name)) {
          const data: any = {
            value: el.id,
            title: el.title,
            type: el.name,
            fieldName: el.field,
            fieldOptions: el.props?.options,
            disabled: el.children && el.children.length ? true : false,
          };
          obj[el.id] = { ...data };
          if (el.children && el.children.length) {
            data.children = [];
            el.children[0].forEach(
              (childEl: {
                id: string;
                title: string;
                name: string;
                field: string;
                props: { options: any };
              }) => {
                const cData = {
                  value: childEl.id,
                  title: childEl.title,
                  type: childEl.name,
                  fieldName: childEl.field,
                  fieldOptions: childEl.props?.options,
                };
                obj[childEl.id] = { ...cData };
                data.children.push(cData);
              },
            );
          }
          tree.push(data);
        }
      },
    );
    setFieldNameTree(tree);
    setFieldNameObj(obj);
  }, [drag]);

  return (
    <>
      <EditableProTable<DataSourceType>
        rowKey="id"
        maxLength={10}
        recordCreatorProps={{
          record: () => {
            return { id: (Math.random() * 1000000).toFixed(0) };
          },
          onClick: () => {
            setEditRow({});
            setIsEdit(true);
          },
        }}
        columns={columns}
        dataSource={dataSource}
        value={dataSource}
        onChange={(data) => {
          setDataSource(data);
          setEditRow({});
          setIsEdit(false);
        }}
        editable={{
          editableKeys,
          onSave: async (rowKey, data) => {
            if (!editRow.fieldText) {
              message.error('请填写完显隐规则再保存！');
              return Promise.reject(false);
            }
            if (!editRow.rule) {
              message.error('“匹配规则”不能为空，请选择再保存！');
              return Promise.reject(false);
            }

            data.fieldNameText = editRow.fieldText;
            switch (editRow.fieldType) {
              case 'radio':
              case 'select':
                if (['eq', 'ne', 'in', 'nin'].includes(editRow.rule || '')) {
                  data.checkValue = editRow.checkValue;
                }
                break;
              case 'datePicker':
              case 'dateRange':
                if (['formula'].includes(editRow.rule || '')) {
                  if (!formulaType || !formulaFlag || !formulaNum || !formulaTime) {
                    message.error('“校验值”不能为空，请填写再保存！');
                    return Promise.reject(false);
                  }
                  data.checkValue = {
                    formulaType,
                    formulaFlag,
                    formulaNum,
                    formulaTime,
                  };
                } else if (['range'].includes(editRow.rule || '')) {
                  data.checkValue = dateRange;
                } else {
                  data.checkValue = date;
                }
                break;
              default:
                break;
            }

            if (!['empty', 'not_empty'].includes(editRow.rule || '') && !data.checkValue) {
              message.error('“校验值”不能为空，请填写再保存！');
              return Promise.reject(false);
            }

            return Promise.resolve(true);
          },
          onChange: setEditableRowKeys,
        }}
      />
    </>
  );
};

export default EditableField;
